#pacman::p_install_gh("systats/binoculaR")
pacman::p_load(tidyverse, haven, magrittr, binoculaR)

Load in Data

ss <- get(load(url("https://github.com/favstats/GodlyGovernance/raw/master/data/arab4.Rdata")))
Warning in .Internal(exists(x, envir, mode, inherits)) :
  closing unused connection 3 (https://github.com/favstats/GodlyGovernance/raw/master/data/arab4.sav)

Inspect Data

#b_select <- binoculaR::binoculaR(arab4)
#dput(b_select$var_codes)
index <- c("country","wt" ,"sample" ,"a1", "q1", "q2", "q13", "q5182", 
"q5184", "q6013", "q6014", "q6018", "q60118", "q605a", "q6061", "q6062", 
"q6063", "q6064", "q6071", "q6074", "q6076", "q707", "q708", 
"q7114", "q1001", "q1002", "q1003", "t1003", "q1004", "q1005", 
"q609", "q6101", "q6106", "q1012", "q1012a", "q1016")
arab4 %<>%
  select(index)
arab4
# save(arab4, file = "data/arab4.Rdata")

Filter Data

Recode Data

arab3 %<>% 
  mutate(cntry = sjmisc::to_label(country)) %>% 
  mutate(region = sjmisc::to_label(a1)) %>% 
  mutate(governorate = sjmisc::to_label(q1)) %>%
  mutate(district = sjmisc::to_label(q2)) 
Error in mutate_impl(.data, dots) : 
  Evaluation error: object 'q2' not found.

Factor Analysis

view_df2 <- function (x, weight.by = NULL, altr.row.col = TRUE, show.id = TRUE, 
  show.type = FALSE, show.values = TRUE, show.string.values = FALSE, 
  show.labels = TRUE, show.frq = FALSE, show.prc = FALSE, 
  show.wtd.frq = FALSE, show.wtd.prc = FALSE, show.na = FALSE, 
  max.len = 15, sort.by.name = FALSE, wrap.labels = 50, hide.progress = FALSE, 
  CSS = NULL, encoding = NULL, file = NULL, use.viewer = TRUE, 
  no.output = FALSE, remove.spaces = TRUE) 
{
  get.encoding <- function(encoding, data = NULL) {
  if (is.null(encoding)) {
    if (!is.null(data) && is.data.frame(data)) {
      # get variable label
      labs <- sjlabelled::get_label(data[[1]])
      # check if vectors of data frame have
      # any valid label. else, default to utf-8
      if (!is.null(labs) && is.character(labs))
        encoding <- Encoding(sjlabelled::get_label(data[[1]]))
      else
        encoding <- "UTF-8"
      # unknown encoding? default to utf-8
      if (encoding == "unknown") encoding <- "UTF-8"
    } else if (.Platform$OS.type == "unix")
      encoding <- "UTF-8"
    else
      encoding <- "Windows-1252"
  }
  return(encoding)
}
  has_value_labels <- function(x) {
  !(is.null(attr(x, "labels", exact = T)) && is.null(attr(x, "value.labels", exact = T)))
}
  sju.rmspc <- function(html.table) {
  cleaned <- gsub("      <", "<", html.table, fixed = TRUE, useBytes = TRUE)
  cleaned <- gsub("    <", "<", cleaned, fixed = TRUE, useBytes = TRUE)
  cleaned <- gsub("  <", "<", cleaned, fixed = TRUE, useBytes = TRUE)
  return(cleaned)
}
  
  encoding <- get.encoding(encoding, x)
  if (!is.data.frame(x)) 
    stop("Parameter needs to be a data frame!", call. = FALSE)
  df.var <- sjlabelled::get_label(x)
  df.val <- sjlabelled::get_labels(x)
  colcnt <- ncol(x)
  id <- seq_len(colcnt)
  if (sort.by.name) 
    id <- id[order(colnames(x))]
  tag.table <- "table"
  tag.thead <- "thead"
  tag.tdata <- "tdata"
  tag.arc <- "arc"
  tag.caption <- "caption"
  tag.omit <- "omit"
  css.table <- "border-collapse:collapse; border:none;"
  css.thead <- "border-bottom:double; font-style:italic; font-weight:normal; padding:0.2cm; text-align:left; vertical-align:top;"
  css.tdata <- "padding:0.2cm; text-align:left; vertical-align:top;"
  css.arc <- "background-color:#eeeeee"
  css.caption <- "font-weight: bold; text-align:left;"
  css.omit <- "color:#999999;"
  if (!is.null(CSS)) {
    if (!is.null(CSS[["css.table"]])) 
      css.table <- ifelse(substring(CSS[["css.table"]], 
        1, 1) == "+", paste0(css.table, substring(CSS[["css.table"]], 
        2)), CSS[["css.table"]])
    if (!is.null(CSS[["css.thead"]])) 
      css.thead <- ifelse(substring(CSS[["css.thead"]], 
        1, 1) == "+", paste0(css.thead, substring(CSS[["css.thead"]], 
        2)), CSS[["css.thead"]])
    if (!is.null(CSS[["css.tdata"]])) 
      css.tdata <- ifelse(substring(CSS[["css.tdata"]], 
        1, 1) == "+", paste0(css.tdata, substring(CSS[["css.tdata"]], 
        2)), CSS[["css.tdata"]])
    if (!is.null(CSS[["css.arc"]])) 
      css.arc <- ifelse(substring(CSS[["css.arc"]], 1, 
        1) == "+", paste0(css.arc, substring(CSS[["css.arc"]], 
        2)), CSS[["css.arc"]])
    if (!is.null(CSS[["css.caption"]])) 
      css.caption <- ifelse(substring(CSS[["css.caption"]], 
        1, 1) == "+", paste0(css.caption, substring(CSS[["css.caption"]], 
        2)), CSS[["css.caption"]])
    if (!is.null(CSS[["css.omit"]])) 
      css.omit <- ifelse(substring(CSS[["css.omit"]], 
        1, 1) == "+", paste0(css.omit, substring(CSS[["css.omit"]], 
        2)), CSS[["css.omit"]])
  }
  page.style <- sprintf("<style>\nhtml, body { background-color: white; }\n%s { %s }\n.%s { %s }\n.%s { %s }\n.%s { %s }\n%s { %s }\n.%s { %s }\n</style>", 
    tag.table, css.table, tag.thead, css.thead, tag.tdata, 
    css.tdata, tag.arc, css.arc, tag.caption, css.caption, 
    tag.omit, css.omit)
  toWrite <- sprintf("<html>\n<head>\n<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n%s\n</head>\n<body>\n", 
    encoding, page.style)
  page.content <- sprintf("<table>\n  <caption>Data frame: %s</caption>\n", 
    deparse(substitute(x)))
  page.content <- paste0(page.content, "  <tr>\n    ")
  if (show.id) 
    page.content <- paste0(page.content, "<th class=\"thead\">ID</th>")
  page.content <- paste0(page.content, "<th class=\"thead\">Name</th>")
  if (show.type) 
    page.content <- paste0(page.content, "<th class=\"thead\">Type</th>")
  page.content <- paste0(page.content, "<th class=\"thead\">Label</th>")
  if (show.na) 
    page.content <- paste0(page.content, "<th class=\"thead\">missings</th>")
  if (show.values) 
    page.content <- paste0(page.content, "<th class=\"thead\">Values</th>")
  if (show.labels) 
    page.content <- paste0(page.content, "<th class=\"thead\">Value Labels</th>")
  if (show.frq) 
    page.content <- paste0(page.content, "<th class=\"thead\">Freq.</th>")
  if (show.prc) 
    page.content <- paste0(page.content, "<th class=\"thead\">%</th>")
  if (show.wtd.frq) 
    page.content <- paste0(page.content, "<th class=\"thead\">weighted Freq.</th>")
  if (show.wtd.prc) 
    page.content <- paste0(page.content, "<th class=\"thead\">weighted %</th>")
  page.content <- paste0(page.content, "\n  </tr>\n")
  if (!hide.progress) 
    pb <- utils::txtProgressBar(min = 0, max = colcnt, style = 3)
  for (ccnt in seq_len(colcnt)) {
    index <- id[ccnt]
    arcstring <- ""
    if (altr.row.col) 
      arcstring <- ifelse(sjmisc::is_even(ccnt), " arc", 
        "")
    page.content <- paste0(page.content, "  <tr>\n")
    if (show.id) 
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%i</td>\n", 
        arcstring, index))
    if (!is.list(x[[index]]) && !is.null(sjlabelled::get_note(x[[index]]))) 
      td.title.tag <- sprintf(" title=\"%s\"", sjlabelled::get_note(x[[index]]))
    else td.title.tag <- ""
    page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\"%s>%s</td>\n", 
      arcstring, td.title.tag, colnames(x)[index]))
    if (show.type) {
      vartype <- sjmisc::var_type(x[[index]])
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, vartype))
    }
    if (index <= length(df.var)) {
      varlab <- df.var[index]
      if (!is.null(wrap.labels)) {
        varlab <- sjmisc::word_wrap(varlab, wrap.labels, 
          "<br>")
      }
    }
    else {
      varlab <- "<NA>"
    }
    page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
      arcstring, varlab))
    if (show.na) {
      if (is.list(x[[index]])) {
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\"><span class=\"omit\">&lt;list&gt;</span></td>\n", 
          arcstring))
      }
      else {
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%i (%.2f%%)</td>\n", 
          arcstring, sum(is.na(x[[index]]), na.rm = T), 
          100 * sum(is.na(x[[index]]), na.rm = T)/nrow(x)))
      }
    }
    if (is.numeric(x[[index]]) && !has_value_labels(x[[index]])) {
      if (show.values || show.labels) {
        valstring <- paste0(sprintf("%a", range(x[[index]], 
          na.rm = T)), collapse = "-")
        if (show.values && show.labels) {
          colsp <- " colspan=\"2\""
          valstring <- paste0("<em>range: ", valstring, 
            "</em>")
        }
        else {
          colsp <- ""
        }
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\"%s>%s</td>\n", 
          arcstring, colsp, valstring))
      }
    }
    else {
      if (show.values) {
        valstring <- ""
        if (index <= ncol(x)) {
          if (is.list(x[[index]])) {
            valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
          }
          else {
            vals <- sjlabelled::get_values(x[[index]])
            if (!is.null(vals)) {
              loop <- na.omit(seq_len(length(vals))[1:max.len])
              for (i in loop) {
                valstring <- paste0(valstring, vals[i])
                if (i < length(vals)) 
                  valstring <- paste0(valstring, "<br>")
              }
              if (max.len < length(vals)) 
                valstring <- paste0(valstring, "<span class=\"omit\">&lt;...&gt;</span>")
            }
          }
        }
        else {
          valstring <- "<NA>"
        }
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
          arcstring, valstring))
      }
      if (show.labels) {
        valstring <- ""
        if (index <= length(df.val)) {
          if (is.list(x[[index]])) {
            valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
          }
          else {
            vals <- df.val[[index]]
            if (!is.null(vals)) 
              vals <- na.omit(vals)
            if (is.character(x[[index]]) && !is.null(vals) && 
              !sjmisc::is_empty(vals)) {
              if (show.string.values) 
                vals <- sort(vals)
              else vals <- "<span class=\"omit\" title =\"'show.string.values = TRUE' to show values.\">&lt;output omitted&gt;</span>"
            }
            if (!is.null(vals)) {
              loop <- na.omit(seq_len(length(vals))[1:max.len])
              for (i in loop) {
                valstring <- paste0(valstring, vals[i])
                if (i < length(vals)) 
                  valstring <- paste0(valstring, "<br>")
              }
              if (max.len < length(vals)) 
                valstring <- paste0(valstring, "<span class=\"omit\">&lt;... truncated&gt;</span>")
            }
          }
        }
        else {
          valstring <- "<NA>"
        }
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
          arcstring, valstring))
      }
    }
    if (show.frq) {
      if (is.list(x[[index]])) 
        valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
      else valstring <- frq.value(index, x, df.val)
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, valstring))
    }
    if (show.prc) {
      if (is.list(x[[index]])) 
        valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
      else valstring <- prc.value(index, x, df.val)
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, valstring))
    }
    if (show.wtd.frq && !is.null(weight.by)) {
      if (is.list(x[[index]])) 
        valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
      else valstring <- frq.value(index, x, df.val, weight.by)
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, valstring))
    }
    if (show.prc && !is.null(weight.by)) {
      if (is.list(x[[index]])) 
        valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
      else valstring <- prc.value(index, x, df.val, weight.by)
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, valstring))
    }
    if (!hide.progress) 
      utils::setTxtProgressBar(pb, ccnt)
    page.content <- paste0(page.content, "  </tr>\n")
  }
  if (!hide.progress) 
    close(pb)
  page.content <- paste(page.content, "</table>", sep = "\n")
  toWrite <- paste0(toWrite, sprintf("%s\n</body></html>", 
    page.content))
  knitr <- page.content
  knitr <- gsub("class=", "style=", knitr, fixed = TRUE, useBytes = TRUE)
  knitr <- gsub("<table", sprintf("<table style=\"%s\"", css.table), 
    knitr, fixed = TRUE, useBytes = TRUE)
  knitr <- gsub(tag.tdata, css.tdata, knitr, fixed = TRUE, 
    useBytes = TRUE)
  knitr <- gsub(tag.thead, css.thead, knitr, fixed = TRUE, 
    useBytes = TRUE)
  knitr <- gsub(tag.arc, css.arc, knitr, fixed = TRUE, useBytes = TRUE)
  if (remove.spaces) {
    knitr <- sju.rmspc(knitr)
    toWrite <- sju.rmspc(toWrite)
    page.content <- sju.rmspc(page.content)
  }
  structure(class = c("sjTable", "view_df"), list(page.style = page.style, 
    page.content = page.content, output.complete = toWrite, 
    header = NULL, knitr = knitr, file = file, show = !no.output, 
    use.viewer = use.viewer))
}
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCmBgYHtyfQ0KI3BhY21hbjo6cF9pbnN0YWxsX2doKCJzeXN0YXRzL2Jpbm9jdWxhUiIpDQpwYWNtYW46OnBfbG9hZCh0aWR5dmVyc2UsIGhhdmVuLCBtYWdyaXR0ciwgY2FyLCBwc3ljaCwgYmlub2N1bGFSKQ0KYGBgDQoNCiMgTG9hZCBpbiBEYXRhDQoNCmBgYHtyfQ0KYXJhYjQgPC0gcmVhZF9zcHNzKCJkYXRhL2FyYWI0LnNhdiIpDQphcmFiMyA8LSByZWFkX3Nwc3MoImRhdGEvYXJhYjMuc2F2IikNCg0KIyBhcmFiNCA8LSBnZXQobG9hZCh1cmwoImh0dHBzOi8vZ2l0aHViLmNvbS9mYXZzdGF0cy9Hb2RseUdvdmVybmFuY2UvcmF3L21hc3Rlci9kYXRhL2FyYWI0LlJkYXRhIikpKQ0KDQpgYGANCg0KIyBJbnNwZWN0IERhdGENCg0KYGBge3J9DQojYl9zZWxlY3QgPC0gYmlub2N1bGFSOjpiaW5vY3VsYVIoYXJhYjQpDQojZHB1dChiX3NlbGVjdCR2YXJfY29kZXMpDQoNCmluZGV4IDwtIGMoImNvdW50cnkiLCJ3dCIgLCJzYW1wbGUiICwiYTEiLCAicTEiLCAicTIiLCAicTEzIiwgInE1MTgyIiwgDQoicTUxODQiLCAicTYwMTMiLCAicTYwMTQiLCAicTYwMTgiLCAicTYwMTE4IiwgInE2MDVhIiwgInE2MDYxIiwgInE2MDYyIiwgDQoicTYwNjMiLCAicTYwNjQiLCAicTYwNzEiLCAicTYwNzQiLCAicTYwNzYiLCAicTcwNyIsICJxNzA4IiwgDQoicTcxMTQiLCAicTEwMDEiLCAicTEwMDIiLCAicTEwMDMiLCAidDEwMDMiLCAicTEwMDQiLCAicTEwMDUiLCANCiJxNjA5IiwgInE2MTAxIiwgInE2MTA2IiwgInExMDEyIiwgInExMDEyYSIsICJxMTAxNiIpDQoNCmFyYWI0ICU8PiUNCiAgc2VsZWN0KGluZGV4KQ0KDQphcmFiNA0KIyBzYXZlKGFyYWI0LCBmaWxlID0gImRhdGEvYXJhYjQuUmRhdGEiKQ0KYGBgDQoNCiMgRmlsdGVyIERhdGENCg0KYGBge3J9DQphcmFiNCAlPD4lDQogIGZpbHRlcihxMTAxMiA9PSAxKSAlPiUjb25seSBNdXNsaW1zDQogIG11dGF0ZShzYW1wbGUgPSBpZmVsc2UoaXMubmEoc2FtcGxlKSB8IHNhbXBsZSA9PSAxLCAxLCAyKSkgJT4lIA0KICBmaWx0ZXIoc2FtcGxlICE9IDIpICNvbmx5IG5vbi1yZWZ1Z2Vlcw0KDQphcmFiMyAlPD4lDQogIGZpbHRlcihxMTAxMiA9PSAxKSAjb25seSBNdXNsaW1zDQoNCmFyYWIzDQphcmFiNA0KYGBgDQoNCiMgUmVjb2RlIERhdGENCg0KYGBge3J9DQp0YWJsZShhcmFiNCRjb3VudHJ5KQ0KDQphcmFiNCAlPD4lIA0KICBtdXRhdGUoY250cnkgPSBzam1pc2M6OnRvX2xhYmVsKGNvdW50cnkpKSAlPiUgDQogIG11dGF0ZShyZWdpb24gPSBzam1pc2M6OnRvX2xhYmVsKGExKSkgJT4lIA0KICBtdXRhdGUoZ292ZXJub3JhdGUgPSBzam1pc2M6OnRvX2xhYmVsKHExKSkgJT4lDQogIG11dGF0ZShkaXN0cmljdCA9IHNqbWlzYzo6dG9fbGFiZWwocTIpKSANCg0KIyBEZXBlbmRlbnQgVmFyaWFibGUNCmFyYWI0ICU8PiUgDQogIG11dGF0ZShpc2xhbWlzdHBhcnRpZXMgPSBpZmVsc2UocTUxODIgPiA1LCBOQSwgNSAtIHE1MTgyKSkgJT4lIA0KICBtdXRhdGUoaXNsYW1pc3Rnb3YgPSBpZmVsc2UocTUxODQgPiA1LCBOQSwgNSAtIHE1MTg0KSkgJT4lIA0KICBtdXRhdGUocmVsaWdpbnRlcmZlcmUgPSBpZmVsc2UocTYwNjEgPiA1LCBOQSwgcTYwNjEpKSAlPiUgDQogIG11dGF0ZShyZWxpZ2xlYWRlcnMgPSBpZmVsc2UocTYwNjIgPiA1LCBOQSwgNSAtIHE2MDYyKSkgJT4lIA0KICBtdXRhdGUocmVsaWdsZWFkZXJzaW5mbCA9IGlmZWxzZShxNjA2MyA+IDUsIE5BLCA1IC0gcTYwNjMpKSAlPiUNCiAgbXV0YXRlKHNlcGVyYXRpb24gPSBpZmVsc2UocTYwNjQgPiA1LCBOQSwgcTYwNjQpKSAlPiUgDQogIG11dGF0ZShyZWxpZ3BhcnR5ID0gUmVjb2RlKHE2MDVhLCAiMSA9IDE7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMiA9IDE7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMyA9IDA7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNCA9IDA7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNSA9IDA7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA5OCA9IDA7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA5OSA9IE5BIikpICU+JSANCiAgbXV0YXRlKHJlbGlncGFydHkyID0gUmVjb2RlKHE2MDVhLCAiMSA9IDU7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIgPSA0Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzID0gMjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNCA9IDE7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDUgPSAzOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDk4ID0gTkE7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOTkgPSBOQSIpKQ0KICANCmFyYWIzICU8PiUgDQogIG11dGF0ZShjbnRyeSA9IHNqbWlzYzo6dG9fbGFiZWwoY291bnRyeSkpICU+JSANCiAgbXV0YXRlKHJlZ2lvbiA9IHNqbWlzYzo6dG9fbGFiZWwoYTEpKSAlPiUgDQogIG11dGF0ZShnb3Zlcm5vcmF0ZSA9IHNqbWlzYzo6dG9fbGFiZWwocTEpKSANCg0KICAjIERlcGVuZGVudCBWYXJpYWJsZQ0KYXJhYjMgJTw+JSANCiAgbXV0YXRlKGlzbGFtaXN0cGFydGllczEgPSBpZmVsc2UocTUxOGEyID4gNSwgTkEsIDUgLSBxNTE4YTIpKSAlPiUgICAgICAgICAgICAgbXV0YXRlKGlzbGFtaXN0cGFydGllczIgPSBpZmVsc2UocTUxOGIyID4gNSwgTkEsIDUgLSBxNTE4YjIpKSAlPiUgDQogIG11dGF0ZShpc2xhbWlzdGdvdiA9IGlmZWxzZShxNTE4NCA+IDUsIE5BLCA1IC0gcTUxODQpKSAlPiUgDQogIG11dGF0ZShyZWxpZ2ludGVyZmVyZSA9IGlmZWxzZShxNjA2MSA+IDUsIE5BLCBxNjA2MSkpICU+JSANCiAgbXV0YXRlKHJlbGlnbGVhZGVycyA9IGlmZWxzZShxNjA2MiA+IDUsIE5BLCA1IC0gcTYwNjIpKSAlPiUgDQogIG11dGF0ZShyZWxpZ2xlYWRlcnNpbmZsID0gaWZlbHNlKHE2MDYzID4gNSwgTkEsIDUgLSBxNjA2MykpICU+JQ0KICBtdXRhdGUoc2VwZXJhdGlvbiA9IGlmZWxzZShxNjA2NCA+IDUsIE5BLCBxNjA2NCkpICU+JSANCiAgbXV0YXRlKHJlbGlncGFydHkgPSBSZWNvZGUocTYwNWEsICIxID0gMTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyID0gMTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA0ID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1ID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDk4ID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDk5ID0gTkEiKSkgJT4lIA0KICBtdXRhdGUocmVsaWdwYXJ0eTIgPSBSZWNvZGUocTYwNWEsICIxID0gNTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMiA9IDQ7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDMgPSAyOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA0ID0gMTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNSA9IDM7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOTggPSBOQTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA5OSA9IE5BIikpDQoNCmFyYWIzJGlzbGFtaXN0cGFydGllczwtcG1heChhcmFiMyRpc2xhbWlzdHBhcnRpZXMxLGFyYWIzJGlzbGFtaXN0cGFydGllczIsbmEucm09VCkNCg0KYXJhYmFsbCA8LSBwbHlyOjpyYmluZC5maWxsKGFyYWI0LGFyYWIzKQ0KDQp0YWJsZShzcyRyZWxpZ3BhcnR5KQ0KdGFibGUoc3MkaXNsYW1pc3Rnb3YpDQp0YWJsZShhcmFiNCRxNjA2MykNCnRhYmxlKGFyYWI0JHE2MDVhKQ0KDQpRNjA1YS4gMXN0IHNlbnRlbmNlOiBJIHByZWZlciBhIHJlbGlnaW91cw0KcG9saXRpY2FsIHBhcnR5IG92ZXIgYSBub24tcmVsaWdpb3VzIHAJMQ0KMg0KMw0KNA0KNQ0KOTgNCjk5CUkgc3Ryb25nbHkgYWdyZWUgd2l0aCB0aGUgMXN0IHNlbnRlbmNlDQpJIGFncmVlIHdpdGggdGhlIDFzdCBzZW50ZW5jZQ0KSSBhZ3JlZSB3aXRoIHRoZSAybmQgc2VudGVuY2UNCkkgc3Ryb25nbHkgYWdyZWUgd2l0aCB0aGUgMm5kIHNlbnRlbmNlDQpEbyBub3QgYWdyZWUgd2l0aCBlaXRoZXIgKERvIG5vdCByZWFkKQ0KRG9uJ3Qga25vdyAoRG8gbm90IHJlYWQpDQpEZWNsaW5lIHRvIGFuc3dlciAoRG8gbm90IHJlYWQpDQoNCg0KYGBgDQoNCiMgRmFjdG9yIEFuYWx5c2lzDQoNCmBgYHtyfQ0KZjMxIDwtIGFyYWJhbGwgJT4lIA0KICBzZWxlY3QoaXNsYW1pc3RwYXJ0aWVzLCBpc2xhbWlzdGdvdiwgDQogICAgICAgICByZWxpZ2xlYWRlcnMsIHJlbGlnbGVhZGVyc2luZmwpICU+JSANCiAgZmEoMSwgcm90YXRlPSJwcm9tYXgiLCAgIA0KICAgICAgICBmbT0icGEiLA0KICAgICAgICBzY29yZXM9InJlZ3Jlc3Npb24iKSAgICAgICAgICAgDQpmYS5kaWFncmFtKGYzMSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpmMzEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpmMzEkZjEkbG9hZGluZ3MgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpmMzEkZjIkbG9hZGluZ3MgIA0KDQpwcmVkaWN0KGYzMSwgYXJhYmFsbCAlPiUgDQogIHNlbGVjdChpc2xhbWlzdHBhcnRpZXMsIGlzbGFtaXN0Z292LCANCiAgICAgICAgIHJlbGlnbGVhZGVycywgcmVsaWdsZWFkZXJzaW5mbCkpICU+JSANCiAgZGF0YS5mcmFtZSgpICU+JSANCiAgY2JpbmQoYXJhYmFsbCkgJT4lIA0KICBnZ3Bsb3QoYWVzKFBBMSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oKSArDQogIGZhY2V0X3dyYXAofmNudHJ5LCBzY2FsZXMgPSAiZnJlZSIpDQoNCmFyYWJhbGwgJT4lIA0KICBzZWxlY3QoaXNsYW1pc3RwYXJ0aWVzLCBpc2xhbWlzdGdvdiwgDQogICAgICAgICByZWxpZ2xlYWRlcnMsIHJlbGlnbGVhZGVyc2luZmwpICU+JSANCiAgYWxwaGEoKSANCg0KYXJhYjQgJT4lIA0KICBzZWxlY3QoaXNsYW1pc3RwYXJ0aWVzLCBpc2xhbWlzdGdvdiwgDQogICAgICAgICByZWxpZ2xlYWRlcnMsIHJlbGlnbGVhZGVyc2luZmwsDQogICAgICAgICByZWxpZ3BhcnR5Miwgc2VwZXJhdGlvbiwNCiAgICAgICAgIHJlbGlnaW50ZXJmZXJlKSAlPiUgDQogIG5hLm9taXQoKSAlPiUgDQogIGNvcigpICANCmBgYA0KDQoNCg0KDQpgYGB7cn0NCnZpZXdfZGYyIDwtIGZ1bmN0aW9uICh4LCB3ZWlnaHQuYnkgPSBOVUxMLCBhbHRyLnJvdy5jb2wgPSBUUlVFLCBzaG93LmlkID0gVFJVRSwgDQogIHNob3cudHlwZSA9IEZBTFNFLCBzaG93LnZhbHVlcyA9IFRSVUUsIHNob3cuc3RyaW5nLnZhbHVlcyA9IEZBTFNFLCANCiAgc2hvdy5sYWJlbHMgPSBUUlVFLCBzaG93LmZycSA9IEZBTFNFLCBzaG93LnByYyA9IEZBTFNFLCANCiAgc2hvdy53dGQuZnJxID0gRkFMU0UsIHNob3cud3RkLnByYyA9IEZBTFNFLCBzaG93Lm5hID0gRkFMU0UsIA0KICBtYXgubGVuID0gMTUsIHNvcnQuYnkubmFtZSA9IEZBTFNFLCB3cmFwLmxhYmVscyA9IDUwLCBoaWRlLnByb2dyZXNzID0gRkFMU0UsIA0KICBDU1MgPSBOVUxMLCBlbmNvZGluZyA9IE5VTEwsIGZpbGUgPSBOVUxMLCB1c2Uudmlld2VyID0gVFJVRSwgDQogIG5vLm91dHB1dCA9IEZBTFNFLCByZW1vdmUuc3BhY2VzID0gVFJVRSkgDQp7DQogIGdldC5lbmNvZGluZyA8LSBmdW5jdGlvbihlbmNvZGluZywgZGF0YSA9IE5VTEwpIHsNCiAgaWYgKGlzLm51bGwoZW5jb2RpbmcpKSB7DQogICAgaWYgKCFpcy5udWxsKGRhdGEpICYmIGlzLmRhdGEuZnJhbWUoZGF0YSkpIHsNCiAgICAgICMgZ2V0IHZhcmlhYmxlIGxhYmVsDQogICAgICBsYWJzIDwtIHNqbGFiZWxsZWQ6OmdldF9sYWJlbChkYXRhW1sxXV0pDQogICAgICAjIGNoZWNrIGlmIHZlY3RvcnMgb2YgZGF0YSBmcmFtZSBoYXZlDQogICAgICAjIGFueSB2YWxpZCBsYWJlbC4gZWxzZSwgZGVmYXVsdCB0byB1dGYtOA0KICAgICAgaWYgKCFpcy5udWxsKGxhYnMpICYmIGlzLmNoYXJhY3RlcihsYWJzKSkNCiAgICAgICAgZW5jb2RpbmcgPC0gRW5jb2Rpbmcoc2psYWJlbGxlZDo6Z2V0X2xhYmVsKGRhdGFbWzFdXSkpDQogICAgICBlbHNlDQogICAgICAgIGVuY29kaW5nIDwtICJVVEYtOCINCiAgICAgICMgdW5rbm93biBlbmNvZGluZz8gZGVmYXVsdCB0byB1dGYtOA0KICAgICAgaWYgKGVuY29kaW5nID09ICJ1bmtub3duIikgZW5jb2RpbmcgPC0gIlVURi04Ig0KICAgIH0gZWxzZSBpZiAoLlBsYXRmb3JtJE9TLnR5cGUgPT0gInVuaXgiKQ0KICAgICAgZW5jb2RpbmcgPC0gIlVURi04Ig0KICAgIGVsc2UNCiAgICAgIGVuY29kaW5nIDwtICJXaW5kb3dzLTEyNTIiDQogIH0NCiAgcmV0dXJuKGVuY29kaW5nKQ0KfQ0KDQogIGhhc192YWx1ZV9sYWJlbHMgPC0gZnVuY3Rpb24oeCkgew0KICAhKGlzLm51bGwoYXR0cih4LCAibGFiZWxzIiwgZXhhY3QgPSBUKSkgJiYgaXMubnVsbChhdHRyKHgsICJ2YWx1ZS5sYWJlbHMiLCBleGFjdCA9IFQpKSkNCn0NCg0KICBzanUucm1zcGMgPC0gZnVuY3Rpb24oaHRtbC50YWJsZSkgew0KICBjbGVhbmVkIDwtIGdzdWIoIiAgICAgIDwiLCAiPCIsIGh0bWwudGFibGUsIGZpeGVkID0gVFJVRSwgdXNlQnl0ZXMgPSBUUlVFKQ0KICBjbGVhbmVkIDwtIGdzdWIoIiAgICA8IiwgIjwiLCBjbGVhbmVkLCBmaXhlZCA9IFRSVUUsIHVzZUJ5dGVzID0gVFJVRSkNCiAgY2xlYW5lZCA8LSBnc3ViKCIgIDwiLCAiPCIsIGNsZWFuZWQsIGZpeGVkID0gVFJVRSwgdXNlQnl0ZXMgPSBUUlVFKQ0KICByZXR1cm4oY2xlYW5lZCkNCn0NCiAgDQogIGVuY29kaW5nIDwtIGdldC5lbmNvZGluZyhlbmNvZGluZywgeCkNCiAgaWYgKCFpcy5kYXRhLmZyYW1lKHgpKSANCiAgICBzdG9wKCJQYXJhbWV0ZXIgbmVlZHMgdG8gYmUgYSBkYXRhIGZyYW1lISIsIGNhbGwuID0gRkFMU0UpDQogIGRmLnZhciA8LSBzamxhYmVsbGVkOjpnZXRfbGFiZWwoeCkNCiAgZGYudmFsIDwtIHNqbGFiZWxsZWQ6OmdldF9sYWJlbHMoeCkNCiAgY29sY250IDwtIG5jb2woeCkNCiAgaWQgPC0gc2VxX2xlbihjb2xjbnQpDQogIGlmIChzb3J0LmJ5Lm5hbWUpIA0KICAgIGlkIDwtIGlkW29yZGVyKGNvbG5hbWVzKHgpKV0NCiAgdGFnLnRhYmxlIDwtICJ0YWJsZSINCiAgdGFnLnRoZWFkIDwtICJ0aGVhZCINCiAgdGFnLnRkYXRhIDwtICJ0ZGF0YSINCiAgdGFnLmFyYyA8LSAiYXJjIg0KICB0YWcuY2FwdGlvbiA8LSAiY2FwdGlvbiINCiAgdGFnLm9taXQgPC0gIm9taXQiDQogIGNzcy50YWJsZSA8LSAiYm9yZGVyLWNvbGxhcHNlOmNvbGxhcHNlOyBib3JkZXI6bm9uZTsiDQogIGNzcy50aGVhZCA8LSAiYm9yZGVyLWJvdHRvbTpkb3VibGU7IGZvbnQtc3R5bGU6aXRhbGljOyBmb250LXdlaWdodDpub3JtYWw7IHBhZGRpbmc6MC4yY207IHRleHQtYWxpZ246bGVmdDsgdmVydGljYWwtYWxpZ246dG9wOyINCiAgY3NzLnRkYXRhIDwtICJwYWRkaW5nOjAuMmNtOyB0ZXh0LWFsaWduOmxlZnQ7IHZlcnRpY2FsLWFsaWduOnRvcDsiDQogIGNzcy5hcmMgPC0gImJhY2tncm91bmQtY29sb3I6I2VlZWVlZSINCiAgY3NzLmNhcHRpb24gPC0gImZvbnQtd2VpZ2h0OiBib2xkOyB0ZXh0LWFsaWduOmxlZnQ7Ig0KICBjc3Mub21pdCA8LSAiY29sb3I6Izk5OTk5OTsiDQogIGlmICghaXMubnVsbChDU1MpKSB7DQogICAgaWYgKCFpcy5udWxsKENTU1tbImNzcy50YWJsZSJdXSkpIA0KICAgICAgY3NzLnRhYmxlIDwtIGlmZWxzZShzdWJzdHJpbmcoQ1NTW1siY3NzLnRhYmxlIl1dLCANCiAgICAgICAgMSwgMSkgPT0gIisiLCBwYXN0ZTAoY3NzLnRhYmxlLCBzdWJzdHJpbmcoQ1NTW1siY3NzLnRhYmxlIl1dLCANCiAgICAgICAgMikpLCBDU1NbWyJjc3MudGFibGUiXV0pDQogICAgaWYgKCFpcy5udWxsKENTU1tbImNzcy50aGVhZCJdXSkpIA0KICAgICAgY3NzLnRoZWFkIDwtIGlmZWxzZShzdWJzdHJpbmcoQ1NTW1siY3NzLnRoZWFkIl1dLCANCiAgICAgICAgMSwgMSkgPT0gIisiLCBwYXN0ZTAoY3NzLnRoZWFkLCBzdWJzdHJpbmcoQ1NTW1siY3NzLnRoZWFkIl1dLCANCiAgICAgICAgMikpLCBDU1NbWyJjc3MudGhlYWQiXV0pDQogICAgaWYgKCFpcy5udWxsKENTU1tbImNzcy50ZGF0YSJdXSkpIA0KICAgICAgY3NzLnRkYXRhIDwtIGlmZWxzZShzdWJzdHJpbmcoQ1NTW1siY3NzLnRkYXRhIl1dLCANCiAgICAgICAgMSwgMSkgPT0gIisiLCBwYXN0ZTAoY3NzLnRkYXRhLCBzdWJzdHJpbmcoQ1NTW1siY3NzLnRkYXRhIl1dLCANCiAgICAgICAgMikpLCBDU1NbWyJjc3MudGRhdGEiXV0pDQogICAgaWYgKCFpcy5udWxsKENTU1tbImNzcy5hcmMiXV0pKSANCiAgICAgIGNzcy5hcmMgPC0gaWZlbHNlKHN1YnN0cmluZyhDU1NbWyJjc3MuYXJjIl1dLCAxLCANCiAgICAgICAgMSkgPT0gIisiLCBwYXN0ZTAoY3NzLmFyYywgc3Vic3RyaW5nKENTU1tbImNzcy5hcmMiXV0sIA0KICAgICAgICAyKSksIENTU1tbImNzcy5hcmMiXV0pDQogICAgaWYgKCFpcy5udWxsKENTU1tbImNzcy5jYXB0aW9uIl1dKSkgDQogICAgICBjc3MuY2FwdGlvbiA8LSBpZmVsc2Uoc3Vic3RyaW5nKENTU1tbImNzcy5jYXB0aW9uIl1dLCANCiAgICAgICAgMSwgMSkgPT0gIisiLCBwYXN0ZTAoY3NzLmNhcHRpb24sIHN1YnN0cmluZyhDU1NbWyJjc3MuY2FwdGlvbiJdXSwgDQogICAgICAgIDIpKSwgQ1NTW1siY3NzLmNhcHRpb24iXV0pDQogICAgaWYgKCFpcy5udWxsKENTU1tbImNzcy5vbWl0Il1dKSkgDQogICAgICBjc3Mub21pdCA8LSBpZmVsc2Uoc3Vic3RyaW5nKENTU1tbImNzcy5vbWl0Il1dLCANCiAgICAgICAgMSwgMSkgPT0gIisiLCBwYXN0ZTAoY3NzLm9taXQsIHN1YnN0cmluZyhDU1NbWyJjc3Mub21pdCJdXSwgDQogICAgICAgIDIpKSwgQ1NTW1siY3NzLm9taXQiXV0pDQogIH0NCiAgcGFnZS5zdHlsZSA8LSBzcHJpbnRmKCI8c3R5bGU+XG5odG1sLCBib2R5IHsgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IH1cbiVzIHsgJXMgfVxuLiVzIHsgJXMgfVxuLiVzIHsgJXMgfVxuLiVzIHsgJXMgfVxuJXMgeyAlcyB9XG4uJXMgeyAlcyB9XG48L3N0eWxlPiIsIA0KICAgIHRhZy50YWJsZSwgY3NzLnRhYmxlLCB0YWcudGhlYWQsIGNzcy50aGVhZCwgdGFnLnRkYXRhLCANCiAgICBjc3MudGRhdGEsIHRhZy5hcmMsIGNzcy5hcmMsIHRhZy5jYXB0aW9uLCBjc3MuY2FwdGlvbiwgDQogICAgdGFnLm9taXQsIGNzcy5vbWl0KQ0KICB0b1dyaXRlIDwtIHNwcmludGYoIjxodG1sPlxuPGhlYWQ+XG48bWV0YSBodHRwLWVxdWl2PVwiQ29udGVudC10eXBlXCIgY29udGVudD1cInRleHQvaHRtbDtjaGFyc2V0PSVzXCI+XG4lc1xuPC9oZWFkPlxuPGJvZHk+XG4iLCANCiAgICBlbmNvZGluZywgcGFnZS5zdHlsZSkNCiAgcGFnZS5jb250ZW50IDwtIHNwcmludGYoIjx0YWJsZT5cbiAgPGNhcHRpb24+RGF0YSBmcmFtZTogJXM8L2NhcHRpb24+XG4iLCANCiAgICBkZXBhcnNlKHN1YnN0aXR1dGUoeCkpKQ0KICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgIiAgPHRyPlxuICAgICIpDQogIGlmIChzaG93LmlkKSANCiAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgIjx0aCBjbGFzcz1cInRoZWFkXCI+SUQ8L3RoPiIpDQogIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiPHRoIGNsYXNzPVwidGhlYWRcIj5OYW1lPC90aD4iKQ0KICBpZiAoc2hvdy50eXBlKSANCiAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgIjx0aCBjbGFzcz1cInRoZWFkXCI+VHlwZTwvdGg+IikNCiAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICI8dGggY2xhc3M9XCJ0aGVhZFwiPkxhYmVsPC90aD4iKQ0KICBpZiAoc2hvdy5uYSkgDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICI8dGggY2xhc3M9XCJ0aGVhZFwiPm1pc3NpbmdzPC90aD4iKQ0KICBpZiAoc2hvdy52YWx1ZXMpIA0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiPHRoIGNsYXNzPVwidGhlYWRcIj5WYWx1ZXM8L3RoPiIpDQogIGlmIChzaG93LmxhYmVscykgDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICI8dGggY2xhc3M9XCJ0aGVhZFwiPlZhbHVlIExhYmVsczwvdGg+IikNCiAgaWYgKHNob3cuZnJxKSANCiAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgIjx0aCBjbGFzcz1cInRoZWFkXCI+RnJlcS48L3RoPiIpDQogIGlmIChzaG93LnByYykgDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICI8dGggY2xhc3M9XCJ0aGVhZFwiPiU8L3RoPiIpDQogIGlmIChzaG93Lnd0ZC5mcnEpIA0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiPHRoIGNsYXNzPVwidGhlYWRcIj53ZWlnaHRlZCBGcmVxLjwvdGg+IikNCiAgaWYgKHNob3cud3RkLnByYykgDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICI8dGggY2xhc3M9XCJ0aGVhZFwiPndlaWdodGVkICU8L3RoPiIpDQogIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiXG4gIDwvdHI+XG4iKQ0KICBpZiAoIWhpZGUucHJvZ3Jlc3MpIA0KICAgIHBiIDwtIHV0aWxzOjp0eHRQcm9ncmVzc0JhcihtaW4gPSAwLCBtYXggPSBjb2xjbnQsIHN0eWxlID0gMykNCiAgZm9yIChjY250IGluIHNlcV9sZW4oY29sY250KSkgew0KICAgIGluZGV4IDwtIGlkW2NjbnRdDQogICAgYXJjc3RyaW5nIDwtICIiDQogICAgaWYgKGFsdHIucm93LmNvbCkgDQogICAgICBhcmNzdHJpbmcgPC0gaWZlbHNlKHNqbWlzYzo6aXNfZXZlbihjY250KSwgIiBhcmMiLCANCiAgICAgICAgIiIpDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICIgIDx0cj5cbiIpDQogICAgaWYgKHNob3cuaWQpIA0KICAgICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsIHNwcmludGYoIiAgICA8dGQgY2xhc3M9XCJ0ZGF0YSVzXCI+JWk8L3RkPlxuIiwgDQogICAgICAgIGFyY3N0cmluZywgaW5kZXgpKQ0KICAgIGlmICghaXMubGlzdCh4W1tpbmRleF1dKSAmJiAhaXMubnVsbChzamxhYmVsbGVkOjpnZXRfbm90ZSh4W1tpbmRleF1dKSkpIA0KICAgICAgdGQudGl0bGUudGFnIDwtIHNwcmludGYoIiB0aXRsZT1cIiVzXCIiLCBzamxhYmVsbGVkOjpnZXRfbm90ZSh4W1tpbmRleF1dKSkNCiAgICBlbHNlIHRkLnRpdGxlLnRhZyA8LSAiIg0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiJXM+JXM8L3RkPlxuIiwgDQogICAgICBhcmNzdHJpbmcsIHRkLnRpdGxlLnRhZywgY29sbmFtZXMoeClbaW5kZXhdKSkNCiAgICBpZiAoc2hvdy50eXBlKSB7DQogICAgICB2YXJ0eXBlIDwtIHNqbWlzYzo6dmFyX3R5cGUoeFtbaW5kZXhdXSkNCiAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPiVzPC90ZD5cbiIsIA0KICAgICAgICBhcmNzdHJpbmcsIHZhcnR5cGUpKQ0KICAgIH0NCiAgICBpZiAoaW5kZXggPD0gbGVuZ3RoKGRmLnZhcikpIHsNCiAgICAgIHZhcmxhYiA8LSBkZi52YXJbaW5kZXhdDQogICAgICBpZiAoIWlzLm51bGwod3JhcC5sYWJlbHMpKSB7DQogICAgICAgIHZhcmxhYiA8LSBzam1pc2M6OndvcmRfd3JhcCh2YXJsYWIsIHdyYXAubGFiZWxzLCANCiAgICAgICAgICAiPGJyPiIpDQogICAgICB9DQogICAgfQ0KICAgIGVsc2Ugew0KICAgICAgdmFybGFiIDwtICI8TkE+Ig0KICAgIH0NCiAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIj4lczwvdGQ+XG4iLCANCiAgICAgIGFyY3N0cmluZywgdmFybGFiKSkNCiAgICBpZiAoc2hvdy5uYSkgew0KICAgICAgaWYgKGlzLmxpc3QoeFtbaW5kZXhdXSkpIHsNCiAgICAgICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsIHNwcmludGYoIiAgICA8dGQgY2xhc3M9XCJ0ZGF0YSVzXCI+PHNwYW4gY2xhc3M9XCJvbWl0XCI+Jmx0O2xpc3QmZ3Q7PC9zcGFuPjwvdGQ+XG4iLCANCiAgICAgICAgICBhcmNzdHJpbmcpKQ0KICAgICAgfQ0KICAgICAgZWxzZSB7DQogICAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPiVpICglLjJmJSUpPC90ZD5cbiIsIA0KICAgICAgICAgIGFyY3N0cmluZywgc3VtKGlzLm5hKHhbW2luZGV4XV0pLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAxMDAgKiBzdW0oaXMubmEoeFtbaW5kZXhdXSksIG5hLnJtID0gVCkvbnJvdyh4KSkpDQogICAgICB9DQogICAgfQ0KICAgIGlmIChpcy5udW1lcmljKHhbW2luZGV4XV0pICYmICFoYXNfdmFsdWVfbGFiZWxzKHhbW2luZGV4XV0pKSB7DQogICAgICBpZiAoc2hvdy52YWx1ZXMgfHwgc2hvdy5sYWJlbHMpIHsNCiAgICAgICAgdmFsc3RyaW5nIDwtIHBhc3RlMChzcHJpbnRmKCIlYSIsIHJhbmdlKHhbW2luZGV4XV0sIA0KICAgICAgICAgIG5hLnJtID0gVCkpLCBjb2xsYXBzZSA9ICItIikNCiAgICAgICAgaWYgKHNob3cudmFsdWVzICYmIHNob3cubGFiZWxzKSB7DQogICAgICAgICAgY29sc3AgPC0gIiBjb2xzcGFuPVwiMlwiIg0KICAgICAgICAgIHZhbHN0cmluZyA8LSBwYXN0ZTAoIjxlbT5yYW5nZTogIiwgdmFsc3RyaW5nLCANCiAgICAgICAgICAgICI8L2VtPiIpDQogICAgICAgIH0NCiAgICAgICAgZWxzZSB7DQogICAgICAgICAgY29sc3AgPC0gIiINCiAgICAgICAgfQ0KICAgICAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIiVzPiVzPC90ZD5cbiIsIA0KICAgICAgICAgIGFyY3N0cmluZywgY29sc3AsIHZhbHN0cmluZykpDQogICAgICB9DQogICAgfQ0KICAgIGVsc2Ugew0KICAgICAgaWYgKHNob3cudmFsdWVzKSB7DQogICAgICAgIHZhbHN0cmluZyA8LSAiIg0KICAgICAgICBpZiAoaW5kZXggPD0gbmNvbCh4KSkgew0KICAgICAgICAgIGlmIChpcy5saXN0KHhbW2luZGV4XV0pKSB7DQogICAgICAgICAgICB2YWxzdHJpbmcgPC0gIjxzcGFuIGNsYXNzPVwib21pdFwiPiZsdDtsaXN0Jmd0Ozwvc3Bhbj4iDQogICAgICAgICAgfQ0KICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgdmFscyA8LSBzamxhYmVsbGVkOjpnZXRfdmFsdWVzKHhbW2luZGV4XV0pDQogICAgICAgICAgICBpZiAoIWlzLm51bGwodmFscykpIHsNCiAgICAgICAgICAgICAgbG9vcCA8LSBuYS5vbWl0KHNlcV9sZW4obGVuZ3RoKHZhbHMpKVsxOm1heC5sZW5dKQ0KICAgICAgICAgICAgICBmb3IgKGkgaW4gbG9vcCkgew0KICAgICAgICAgICAgICAgIHZhbHN0cmluZyA8LSBwYXN0ZTAodmFsc3RyaW5nLCB2YWxzW2ldKQ0KICAgICAgICAgICAgICAgIGlmIChpIDwgbGVuZ3RoKHZhbHMpKSANCiAgICAgICAgICAgICAgICAgIHZhbHN0cmluZyA8LSBwYXN0ZTAodmFsc3RyaW5nLCAiPGJyPiIpDQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgaWYgKG1heC5sZW4gPCBsZW5ndGgodmFscykpIA0KICAgICAgICAgICAgICAgIHZhbHN0cmluZyA8LSBwYXN0ZTAodmFsc3RyaW5nLCAiPHNwYW4gY2xhc3M9XCJvbWl0XCI+Jmx0Oy4uLiZndDs8L3NwYW4+IikNCiAgICAgICAgICAgIH0NCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgZWxzZSB7DQogICAgICAgICAgdmFsc3RyaW5nIDwtICI8TkE+Ig0KICAgICAgICB9DQogICAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPiVzPC90ZD5cbiIsIA0KICAgICAgICAgIGFyY3N0cmluZywgdmFsc3RyaW5nKSkNCiAgICAgIH0NCiAgICAgIGlmIChzaG93LmxhYmVscykgew0KICAgICAgICB2YWxzdHJpbmcgPC0gIiINCiAgICAgICAgaWYgKGluZGV4IDw9IGxlbmd0aChkZi52YWwpKSB7DQogICAgICAgICAgaWYgKGlzLmxpc3QoeFtbaW5kZXhdXSkpIHsNCiAgICAgICAgICAgIHZhbHN0cmluZyA8LSAiPHNwYW4gY2xhc3M9XCJvbWl0XCI+Jmx0O2xpc3QmZ3Q7PC9zcGFuPiINCiAgICAgICAgICB9DQogICAgICAgICAgZWxzZSB7DQogICAgICAgICAgICB2YWxzIDwtIGRmLnZhbFtbaW5kZXhdXQ0KICAgICAgICAgICAgaWYgKCFpcy5udWxsKHZhbHMpKSANCiAgICAgICAgICAgICAgdmFscyA8LSBuYS5vbWl0KHZhbHMpDQogICAgICAgICAgICBpZiAoaXMuY2hhcmFjdGVyKHhbW2luZGV4XV0pICYmICFpcy5udWxsKHZhbHMpICYmIA0KICAgICAgICAgICAgICAhc2ptaXNjOjppc19lbXB0eSh2YWxzKSkgew0KICAgICAgICAgICAgICBpZiAoc2hvdy5zdHJpbmcudmFsdWVzKSANCiAgICAgICAgICAgICAgICB2YWxzIDwtIHNvcnQodmFscykNCiAgICAgICAgICAgICAgZWxzZSB2YWxzIDwtICI8c3BhbiBjbGFzcz1cIm9taXRcIiB0aXRsZSA9XCInc2hvdy5zdHJpbmcudmFsdWVzID0gVFJVRScgdG8gc2hvdyB2YWx1ZXMuXCI+Jmx0O291dHB1dCBvbWl0dGVkJmd0Ozwvc3Bhbj4iDQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAoIWlzLm51bGwodmFscykpIHsNCiAgICAgICAgICAgICAgbG9vcCA8LSBuYS5vbWl0KHNlcV9sZW4obGVuZ3RoKHZhbHMpKVsxOm1heC5sZW5dKQ0KICAgICAgICAgICAgICBmb3IgKGkgaW4gbG9vcCkgew0KICAgICAgICAgICAgICAgIHZhbHN0cmluZyA8LSBwYXN0ZTAodmFsc3RyaW5nLCB2YWxzW2ldKQ0KICAgICAgICAgICAgICAgIGlmIChpIDwgbGVuZ3RoKHZhbHMpKSANCiAgICAgICAgICAgICAgICAgIHZhbHN0cmluZyA8LSBwYXN0ZTAodmFsc3RyaW5nLCAiPGJyPiIpDQogICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgaWYgKG1heC5sZW4gPCBsZW5ndGgodmFscykpIA0KICAgICAgICAgICAgICAgIHZhbHN0cmluZyA8LSBwYXN0ZTAodmFsc3RyaW5nLCAiPHNwYW4gY2xhc3M9XCJvbWl0XCI+Jmx0Oy4uLiB0cnVuY2F0ZWQmZ3Q7PC9zcGFuPiIpDQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAgIGVsc2Ugew0KICAgICAgICAgIHZhbHN0cmluZyA8LSAiPE5BPiINCiAgICAgICAgfQ0KICAgICAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIj4lczwvdGQ+XG4iLCANCiAgICAgICAgICBhcmNzdHJpbmcsIHZhbHN0cmluZykpDQogICAgICB9DQogICAgfQ0KICAgIGlmIChzaG93LmZycSkgew0KICAgICAgaWYgKGlzLmxpc3QoeFtbaW5kZXhdXSkpIA0KICAgICAgICB2YWxzdHJpbmcgPC0gIjxzcGFuIGNsYXNzPVwib21pdFwiPiZsdDtsaXN0Jmd0Ozwvc3Bhbj4iDQogICAgICBlbHNlIHZhbHN0cmluZyA8LSBmcnEudmFsdWUoaW5kZXgsIHgsIGRmLnZhbCkNCiAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPiVzPC90ZD5cbiIsIA0KICAgICAgICBhcmNzdHJpbmcsIHZhbHN0cmluZykpDQogICAgfQ0KICAgIGlmIChzaG93LnByYykgew0KICAgICAgaWYgKGlzLmxpc3QoeFtbaW5kZXhdXSkpIA0KICAgICAgICB2YWxzdHJpbmcgPC0gIjxzcGFuIGNsYXNzPVwib21pdFwiPiZsdDtsaXN0Jmd0Ozwvc3Bhbj4iDQogICAgICBlbHNlIHZhbHN0cmluZyA8LSBwcmMudmFsdWUoaW5kZXgsIHgsIGRmLnZhbCkNCiAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPiVzPC90ZD5cbiIsIA0KICAgICAgICBhcmNzdHJpbmcsIHZhbHN0cmluZykpDQogICAgfQ0KICAgIGlmIChzaG93Lnd0ZC5mcnEgJiYgIWlzLm51bGwod2VpZ2h0LmJ5KSkgew0KICAgICAgaWYgKGlzLmxpc3QoeFtbaW5kZXhdXSkpIA0KICAgICAgICB2YWxzdHJpbmcgPC0gIjxzcGFuIGNsYXNzPVwib21pdFwiPiZsdDtsaXN0Jmd0Ozwvc3Bhbj4iDQogICAgICBlbHNlIHZhbHN0cmluZyA8LSBmcnEudmFsdWUoaW5kZXgsIHgsIGRmLnZhbCwgd2VpZ2h0LmJ5KQ0KICAgICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsIHNwcmludGYoIiAgICA8dGQgY2xhc3M9XCJ0ZGF0YSVzXCI+JXM8L3RkPlxuIiwgDQogICAgICAgIGFyY3N0cmluZywgdmFsc3RyaW5nKSkNCiAgICB9DQogICAgaWYgKHNob3cucHJjICYmICFpcy5udWxsKHdlaWdodC5ieSkpIHsNCiAgICAgIGlmIChpcy5saXN0KHhbW2luZGV4XV0pKSANCiAgICAgICAgdmFsc3RyaW5nIDwtICI8c3BhbiBjbGFzcz1cIm9taXRcIj4mbHQ7bGlzdCZndDs8L3NwYW4+Ig0KICAgICAgZWxzZSB2YWxzdHJpbmcgPC0gcHJjLnZhbHVlKGluZGV4LCB4LCBkZi52YWwsIHdlaWdodC5ieSkNCiAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPiVzPC90ZD5cbiIsIA0KICAgICAgICBhcmNzdHJpbmcsIHZhbHN0cmluZykpDQogICAgfQ0KICAgIGlmICghaGlkZS5wcm9ncmVzcykgDQogICAgICB1dGlsczo6c2V0VHh0UHJvZ3Jlc3NCYXIocGIsIGNjbnQpDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICIgIDwvdHI+XG4iKQ0KICB9DQogIGlmICghaGlkZS5wcm9ncmVzcykgDQogICAgY2xvc2UocGIpDQogIHBhZ2UuY29udGVudCA8LSBwYXN0ZShwYWdlLmNvbnRlbnQsICI8L3RhYmxlPiIsIHNlcCA9ICJcbiIpDQogIHRvV3JpdGUgPC0gcGFzdGUwKHRvV3JpdGUsIHNwcmludGYoIiVzXG48L2JvZHk+PC9odG1sPiIsIA0KICAgIHBhZ2UuY29udGVudCkpDQogIGtuaXRyIDwtIHBhZ2UuY29udGVudA0KICBrbml0ciA8LSBnc3ViKCJjbGFzcz0iLCAic3R5bGU9Iiwga25pdHIsIGZpeGVkID0gVFJVRSwgdXNlQnl0ZXMgPSBUUlVFKQ0KICBrbml0ciA8LSBnc3ViKCI8dGFibGUiLCBzcHJpbnRmKCI8dGFibGUgc3R5bGU9XCIlc1wiIiwgY3NzLnRhYmxlKSwgDQogICAga25pdHIsIGZpeGVkID0gVFJVRSwgdXNlQnl0ZXMgPSBUUlVFKQ0KICBrbml0ciA8LSBnc3ViKHRhZy50ZGF0YSwgY3NzLnRkYXRhLCBrbml0ciwgZml4ZWQgPSBUUlVFLCANCiAgICB1c2VCeXRlcyA9IFRSVUUpDQogIGtuaXRyIDwtIGdzdWIodGFnLnRoZWFkLCBjc3MudGhlYWQsIGtuaXRyLCBmaXhlZCA9IFRSVUUsIA0KICAgIHVzZUJ5dGVzID0gVFJVRSkNCiAga25pdHIgPC0gZ3N1Yih0YWcuYXJjLCBjc3MuYXJjLCBrbml0ciwgZml4ZWQgPSBUUlVFLCB1c2VCeXRlcyA9IFRSVUUpDQogIGlmIChyZW1vdmUuc3BhY2VzKSB7DQogICAga25pdHIgPC0gc2p1LnJtc3BjKGtuaXRyKQ0KICAgIHRvV3JpdGUgPC0gc2p1LnJtc3BjKHRvV3JpdGUpDQogICAgcGFnZS5jb250ZW50IDwtIHNqdS5ybXNwYyhwYWdlLmNvbnRlbnQpDQogIH0NCiAgc3RydWN0dXJlKGNsYXNzID0gYygic2pUYWJsZSIsICJ2aWV3X2RmIiksIGxpc3QocGFnZS5zdHlsZSA9IHBhZ2Uuc3R5bGUsIA0KICAgIHBhZ2UuY29udGVudCA9IHBhZ2UuY29udGVudCwgb3V0cHV0LmNvbXBsZXRlID0gdG9Xcml0ZSwgDQogICAgaGVhZGVyID0gTlVMTCwga25pdHIgPSBrbml0ciwgZmlsZSA9IGZpbGUsIHNob3cgPSAhbm8ub3V0cHV0LCANCiAgICB1c2Uudmlld2VyID0gdXNlLnZpZXdlcikpDQp9DQoNCnZpZXdfZGYyKGFyYWI0LCBoaWRlLnByb2dyZXNzID0gVCkNCmBgYA0KDQoNCg==